package rlpw.swing;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Comparator;
import javax.swing.*;
import javax.swing.event.EventListenerList;

public class JOCheckPanel<T> extends JPanel implements View<T> {

    private Model<T> model;
    private CheckModel<T> checked;
    private Filter<T> filter;
    private Comparator<T> sorter;
    private EventListenerList listeners = new EventListenerList();

    public JOCheckPanel() {
        this(new DefaultModel<T>(), null);
    }

    public JOCheckPanel(String title) {
        this(new DefaultModel<T>(), title);
    }

    public JOCheckPanel(Model<T> model) {
        this(model, null);
    }

    public JOCheckPanel(Model<T> model, String title) {
        if (title != null) {
            setBorder(BorderFactory.createTitledBorder(title));
        }
        setFilter(null);
        model.addView(this);
        checked = new DefaultCheckModel<T>(this);
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        updateView();
    }

    public void updateView() {
        removeAll();
        for (final T item : new FilteredList<T>(this)) {
            final JCheckBox cb = new JCheckBox(item.toString(), getCheckModel().isChecked(item));
            cb.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    getCheckModel().setChecked(item, cb.isSelected());
                    fireActionEvent();
                }
            });
            cb.setFocusPainted(false);
            add(cb);

        }
        revalidate();
        repaint();
    }

    public Model<T> getDataModel() {
        return model;
    }

    public void setDataModel(Model<T> model) {
        this.model = model;
        if (getCheckModel() != null) {
            updateView();
        }

    }

    public CheckModel<T> getCheckModel() {
        return checked;

    }

    public SelectModel<T> getSelectModel() {
        return null;
    }

    public Filter<T> getFilter() {
        return filter;
    }

    public void setFilter(Filter<T> filter) {
        if (filter == null) {
            this.filter = new DefaultFilter<T>();
        } else {
            this.filter = filter;
        }
        if (getCheckModel() != null) {
            updateView();
        }
    }

    public void setSorter(Comparator<T> comp) {
        sorter = comp;
        updateView();
    }

    public Comparator<T> getSorter() {
        return sorter;
    }

    public void addActionListener(ActionListener l) {
        listeners.add(ActionListener.class, l);
    }

    public void removeActionListener(ActionListener l) {
        listeners.remove(ActionListener.class, l);
    }

    protected synchronized void fireActionEvent() {
        getDataModel().updateViews();
        ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "");
        for (ActionListener l : listeners.getListeners(ActionListener.class)) {
            l.actionPerformed(event);
        }
    }
}